package com.maikang.exammall.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;

@Log4j2
@Component
public class JsonUtil {
    private ObjectMapper objectMapper;

    @Autowired
    public JsonUtil(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public boolean isValidJSON(String str) {
        try {
            objectMapper.readTree(str);
            return true;
        } catch (IOException e) {
            log.error("invalid json exception", e);
            return false;
        }
    }

    public <T> T jsonToObject(String json, Class<T> resultType) {
        if (!StringUtils.hasLength(json)) {
            throw new IllegalArgumentException("Required json str should not be empty");
        }
        if (!isValidJSON(json)) {
            throw new IllegalArgumentException("input json: " + json + " is invalid");
        }
        try {
            return objectMapper.readValue(json, resultType);
        } catch (IOException e) {
            throw new RuntimeException("Failed to convert json: " + json + " to object", e);
        }

    }

    public <T> List<T> jsonToList(String json, Class<T> resultType) {
        if (!StringUtils.hasLength(json)) {
            throw new IllegalArgumentException("Required json str should not be empty");
        }
        if (!isValidJSON(json)) {
            throw new IllegalArgumentException("input json: " + json + " is invalid");
        }
        try {
            Class<?> clz = Class.forName(resultType.getName());
            JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, clz);
            return objectMapper.readValue(json, type);
        } catch (IOException e) {
            log.error("failed to read json", e);
            throw new RuntimeException("failed to read json: " + json, e);
        } catch (ClassNotFoundException e) {
            log.error("failed to reflect: " + resultType.getName(), e);
            throw new RuntimeException("failed to reflect: " + json, e);
        }
    }

    public String objectToJson(Object obj) {
        if (obj == null) {
            throw new IllegalArgumentException("Required object should not be null to convert to json");
        }

        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert obj: " + obj + " to json", e);
        }
    }

}
